package com.lightningtrade.security.filter;


import com.lightningtrade.security.UserDetails;
import com.lightningtrade.util.JwtTokenUtil;
import com.lightningtrade.util.RedisCache;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;


import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    RedisCache rediscache;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // 获取 用户的token
        String authentication = request.getHeader("Authorization");

        // 不存在token，直接放行
        if(!StringUtils.hasText(authentication)){
            filterChain.doFilter(request, response);
            return;
        }

        // 解析token 获取用户id
        String userid;
        try {
            Claims claims = jwtTokenUtil.parseJWT(authentication);
            userid = claims.getSubject();
        } catch (Exception e) {
            // token解析失败
            e.printStackTrace();
            throw new RuntimeException("\ntoken解析失败\n");
        }

        // 根据用户id 从redis中获取用户授权信息
        String redisKey = "login:" + userid;
        UserDetails loginUser = rediscache.getCacheObject(redisKey);
        if(Objects.isNull(loginUser)){
            throw new RuntimeException("用户未登录");
        }

        // 将用户授权信息(包含权限信息_角色) 封装成 授权令牌 存入SecurityContext
        UsernamePasswordAuthenticationToken authorization =
                new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());

        SecurityContextHolder.getContext().setAuthentication(authorization);

        // 放行
        filterChain.doFilter(request, response);
    }
}